﻿using System;
using Microsoft.Xna.Framework;

namespace TPL.Xna.Common
{
    public class SpriteSheetAnimator : SpritePropertyAnimator<Rectangle>
    {
        private readonly Point _sheetSize;
        private readonly Rectangle _frameSize;
        private readonly bool _randomOrder;

        private Point _currentFrameIndex;

        private static readonly Random _rand = new Random();
        private Rectangle _value;

        public SpriteSheetAnimator(Point sheetSize, Rectangle frameSize, bool randomOrder) :
            base(s => ((ImageSprite)s).SourceRectangle)
        {
            _sheetSize = sheetSize;
            _frameSize = frameSize;
            _randomOrder = randomOrder;
        }

        public override void Initialize()
        {
            _value = new Rectangle(0, 0, _frameSize.Width, _frameSize.Height);
            _currentFrameIndex = _randomOrder
                ? new Point(_rand.Next(_sheetSize.X - 1), _rand.Next(_sheetSize.Y - 1))
                : Point.Zero;
            SetValue(_value);
        }

        protected override void Update(ref Rectangle value, Rectangle delta)
        {
            throw new NotSupportedException();
        }

        protected override Rectangle CalculateDelta()
        {
            throw new NotSupportedException();
        }

        public override IAnimator AttachTo(Sprite sprite)
        {
            if (SpriteCount > 0)
                throw new NotSupportedException("This animator can work with single sprite only");
            return base.AttachTo(sprite);
        }

        public override void Update(GameTime gameTime)
        {
            // Update frame index 
            ++_currentFrameIndex.X;
            if (_currentFrameIndex.X >= _sheetSize.X)
            {
                _currentFrameIndex.X = 0;
                ++_currentFrameIndex.Y;
                if (_currentFrameIndex.Y >= _sheetSize.Y)
                    _currentFrameIndex.Y = 0;
            }
            _value.X = _currentFrameIndex.X * _value.Width;
            _value.Y = _currentFrameIndex.Y * _value.Height;
            SetValue(_value);
        }
    }
}
